home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / utility.lha / utility / strings.C < prev    next >
C/C++ Source or Header  |  1993-08-08  |  5KB  |  279 lines

  1. // $Id: strings.C,v 1.4 92/01/09 11:26:01 dag Exp $
  2. //
  3. // NOTE: internal_buffer_size > 1 required by operator = (char).
  4.  
  5.  
  6. #include <defs.H>
  7. #include <strings.H>
  8. #include <ctype.h>
  9. #include <iostream.h>
  10.  
  11.  
  12. // Set DO_STAT true to collect statistics on string lengths.
  13.  
  14. #define DO_STAT 0
  15.  
  16. #if DO_STAT
  17. #include <statcount.H>
  18. static void Count(int sz)
  19. {
  20.   static StatCount cnt("Distribution of string sizes", 0, 64, 4);
  21.   cnt(sz);
  22. }
  23. #else
  24. #define Count(size)
  25. #endif
  26.  
  27.  
  28. // The following macros handle allocation of string memory, either with
  29. // the internal buffer of by allocating on the heap.
  30.  
  31. #define allocate(str, n) str = n <= internal_buffer_size ? buf : new char[n]
  32. #define deallocate(str) if (str != buf) delete [] str
  33.  
  34.  
  35. // ----------------------------------------------------------------------------
  36. // Constructors, destructor
  37.  
  38. String :: String ()
  39. {
  40.   size = internal_buffer_size;
  41.   allocate(str, internal_buffer_size);
  42. Count(size);
  43.   str[0] = '\0';
  44. }
  45.  
  46.  
  47. String :: String (const char* s)
  48. {
  49.   if (s == nil)
  50.     s = "";
  51.   size = max(strlen(s)+1, internal_buffer_size);
  52.   allocate(str, size);
  53. Count(size);
  54.   strcpy(str, s);
  55. }
  56.  
  57.  
  58. String :: String (const String& s)
  59. {
  60.   size = s.Size();
  61.   allocate(str, size);
  62. Count(size);
  63.   strcpy(str, s.str);
  64. }
  65.  
  66.  
  67. String :: ~String()
  68. {
  69.   deallocate(str);
  70. }
  71.  
  72.  
  73. // ----------------------------------------------------------------------------
  74. // Assignment, assignment operators
  75.  
  76. String& String :: operator = (const String& s)
  77. {
  78.   if (&s != this) {        // same object?
  79.     int len = s.Length();
  80.     if (len >= size) {
  81.       size = len + 1;
  82.       deallocate(str);
  83.       allocate(str, size);
  84. Count(size);
  85.     }
  86.     strcpy(str, s.str);
  87.   }
  88.   return *this;
  89. }
  90.  
  91.  
  92. String& String :: operator = (const char* s)
  93. // Note: works even if s == this->str, although "strcpy" is not needed.
  94. {
  95.   if (s == nil)
  96.     s = "";
  97.  
  98.   int len = strlen(s);
  99.   if (len >= size) {
  100.     size = len + 1;
  101.     deallocate(str);
  102.     allocate(str, size);
  103. Count(size);
  104.   }
  105.   strcpy(str, s);
  106.   
  107.   return *this;
  108. }
  109.  
  110.  
  111. String& String :: operator = (char c)
  112. {
  113.   str[0] = c;
  114.   str[1] = '\0';
  115.   return *this;
  116. }
  117.  
  118.  
  119. void String :: operator += (const String& s)
  120. {
  121.   unsigned newlen = Length() + s.Length();
  122.   if (newlen < size)
  123.     strcat(str, s.str);
  124.   else {
  125.     size = newlen + internal_buffer_size;
  126.     char* r = new char[size];
  127. Count(size);
  128.     strcpy(r, str);
  129.     strcat(r, s.str);
  130.     deallocate(str);
  131.     str = r;
  132.   }
  133. }
  134.  
  135.  
  136. void String :: operator += (char c)
  137. {
  138.   const int chunk_size = internal_buffer_size;
  139.  
  140.   unsigned oldlength = Length();
  141.   if (oldlength + 1 >= size) {
  142.     size += chunk_size;
  143.     char* r = new char[size];
  144. Count(size);
  145.     strcpy(r, str);
  146.     deallocate(str);
  147.     str = r;
  148.   }
  149.   str[oldlength] = c;
  150.   str[oldlength+1] = '\0';
  151. }
  152.  
  153.  
  154. String operator + (const String& s1, const String& s2)
  155. {
  156.   String r = s1;
  157.   r += s2;
  158.   return r;
  159. }
  160.  
  161.  
  162. // ----------------------------------------------------------------------------
  163. // Subscripting
  164.  
  165. char String :: operator () (unsigned i) const
  166. {
  167.   if (i < Length())
  168.     return str[i];
  169.   else
  170.     return '\0';
  171. }
  172.  
  173.  
  174. String String :: operator () (unsigned start, unsigned n) const
  175. {
  176.   static char* r = 0;        // temporary storage
  177.   delete r;
  178.  
  179.   unsigned len = Length();
  180.   if (start >= len)
  181.     return "";
  182.   n = min(n, len-start);
  183.   
  184.   r = new char[n + 1];
  185.   strncpy(r, str+start, n);
  186.   r[n] = 0;
  187.   return r;
  188. }
  189.  
  190.  
  191. // ----------------------------------------------------------------------------
  192. // Comparisons
  193.  
  194.  
  195. boolean operator == (const String& s1, const char* s2)
  196. {
  197.   if (s2 == nil)
  198.     s2 = "";
  199.   return s1.str[0] == s2[0] && strcmp(s1.str, s2) == 0;
  200. }
  201.  
  202.  
  203. boolean operator == (char* s1, const String& s2)
  204. {
  205.   if (s1 == nil)
  206.     s1 = "";
  207.   return s1[0] == s2.str[0] && strcmp(s1, s2.str) == 0;
  208. }
  209.  
  210.  
  211. // ----------------------------------------------------------------------------
  212. // Misc. utility functions
  213.  
  214.  
  215. char* String :: Copy() const
  216. {
  217.   char* s = new char[Length() + 1];
  218.   strcpy(s, str);
  219.   return s;
  220. }
  221.  
  222.  
  223. String String :: upper() const
  224. {
  225.   String t = *this;
  226.   register char* p = &t.str[t.Length()];
  227.   while (--p >= t.str)
  228.     if (islower(*p)) *p = toupper(*p);
  229.   return t;
  230. }
  231.  
  232.  
  233. String String :: lower() const
  234. {
  235.   String t = *this;
  236.   register char* p = &t.str[t.Length()];
  237.   while (--p >= t.str)
  238.     if (isupper(*p)) *p = tolower(*p);
  239.   return t;
  240. }
  241.  
  242.  
  243. unsigned String :: Hashval() const
  244. {
  245.   register char* p = str;
  246.   register unsigned h = 0;
  247.   while (*p != 0)
  248.     h += unsigned(*(p++));
  249.   return h;
  250. }
  251.  
  252.  
  253. // ----------------------------------------------------------------------------
  254. // Input/output on streams
  255.  
  256. ostream& operator << (ostream& o, const String& s)
  257. {
  258.   o << s.str;
  259.   return o;
  260. }
  261.  
  262.  
  263. istream& operator >> (istream& i, String& s)
  264. {
  265.   char c;
  266.   s = "";
  267.   
  268.   while (i.get(c) && isspace(c)) // skip to next word
  269.     ;
  270.   if (i) {            // read a word
  271.     do
  272.       s += c;
  273.     while (i.get(c) && !isspace(c));
  274.     if (i)
  275.       i.putback(c);
  276.   }
  277.   return i;
  278. }
  279.